#-*- coding:utf8 -*-
'''기준정보 M'''

__author__ = 'jh,Seo'
__version__ = '0.1'

from django.db import models
import unittest
import datetime
import logging
log = logging.getLogger(__name__)
from django.contrib.auth.models import User


class Groups(models.Model):
    '''그룹코드 (그룹은 모회사의 개념으로 사용된다.)
    '''
    code = models.CharField(max_length=20)
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=2000)

    cdate = models.DateField(blank=True, null=True, default=datetime.date.today())
    udate = models.DateField(blank=True, null=True, default=datetime.date.today())
    ddate = models.DateField(blank=True, null=True)

    class Meta:
        unique_together = ("code",)

    def __unicode__(self):
        return '(' + self.code + ') ' + self.name




class Companies(models.Model):
    '''회사코드 (회사는 개별적으로 유일하지만 드물게 그룹에 속할수 있다.)
    '''
    group = models.ForeignKey(Groups)
    code = models.CharField(max_length=20)
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=2000)

    cdate = models.DateField(blank=True, null=True, default=datetime.date.today())
    udate = models.DateField(blank=True, null=True, default=datetime.date.today())
    ddate = models.DateField(blank=True, null=True)

    class Meta:
        unique_together = ("group", "code",)

    def __unicode__(self):
        return '(' + self.group.code + ', ' + self.code + ') ' + self.name



class Depts(models.Model):
    '''부서'''
    company = models.ForeignKey(Companies)
    code = models.CharField(max_length=20)
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=2000)
    
    expire_date = models.DateField(default=datetime.date(9999, 12, 31))
    sort_no = models.IntegerField(default=1)

    cdate = models.DateField(blank=True, null=True, default=datetime.date.today())
    udate = models.DateField(blank=True, null=True, default=datetime.date.today())
    ddate = models.DateField(blank=True, null=True)

    def __unicode__(self):
        return '(' + self.company.group.code \
            + ', ' + self.company.code \
            + ', ' + self.code \
            + ', ' + str(self.expire_date) \
            + ') ' + self.name

    class Meta:
        unique_together = ('company', "code", "expire_date")


class DeptTrees(models.Model):
    '''부서 클로저 모델
    '''
    ancestor = models.ForeignKey(Depts, related_name='ancestor_depts_id')
    descendant = models.ForeignKey(Depts, related_name='descendant_depts_id')
    path_length = models.IntegerField()

    cdate = models.DateField(blank=True, null=True, default=datetime.date.today())
    udate = models.DateField(blank=True, null=True, default=datetime.date.today())
    ddate = models.DateField(blank=True, null=True)

    class Meta:
        unique_together=('ancestor', 'descendant')

    def __unicode__(self):
        return '( ANC : [' + self.ancestor.__unicode__() + '], ' \
            + 'DES : [' + self.descendant.__unicode__() + '] ' \
            + ') ' + str(self.path_length)
        
        
        
    def append_node(self, to_dept, dept):
        
        nodes = DeptTrees.objects.filter(descendant=to_dept)
        for node in nodes:
            DeptTrees.objects.create(
                ancestor = node.ancestor,
                descendant = dept,
                path_length = (node.path_length + 1)
            )
            
        DeptTrees.objects.create(
            ancestor = dept,
            descendant = dept,
            path_length = 0
        )
        
    def remove_node(self, dept):
        '''
        자신을 포함한 하위 노드를 전부 삭제한다.
        트리가 삭제된다고 부서정보가 삭제되는것은 아니다.
        '''
        nodes = []
        for i in DeptTrees.objects.filter(ancestor = dept):
            nodes.append(i.descendant)
        
        DeptTrees.objects.filter(
            descendant__in = nodes  
        ).delete()
        # 나의 자식노드 정보를 찾아서 삭제한다.
        
        
        
        
    def _find_direct_descendants(self, me):
        '''자식 부서 정보를 반환'''
        nodes = []
        
        dts = DeptTrees.objects.filter(ancestor = me, path_length = 1)
        for node in dts:
            target = node.ancestor
            nodes.append(target)
            
        return nodes
        
        
    def move_node(self, from_dept, to_dept):
        '''
        현재 노드를 대상 노드의 하위로 이동시킨다.'''
        
        me = from_dept
        
        DeptTrees.objects.filter(descendant = from_dept).delete() #일단 내 노드정보 삭제
        self.append_node(to_dept, from_dept) # 내 노드를 새 부모에 자식으로 추가함
        
        nodes = self._find_direct_descendants(me)
        index = 0
        while 1 > len(nodes):
            ''' 자식노드가 남아있으면 '''
            
            from_dept = nodes[index]
            to_dept = me
            
            ''' 재귀호출 하여 처리함'''
            self.move_node(from_dept, to_dept)
            
            index = index + 1;
        
        
        
        



class GroupCodes(models.Model):
    '''그룹 전체에 통용되는 코드
    '''
    group = models.ForeignKey(Groups)

    code = models.CharField(max_length=20)
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=2000)
    
    memo = models.TextField(null=True, blank=True)
    
    used = models.BooleanField(default=True)
    sort_seq = models.IntegerField(default=1)
    
    upper_code = models.ForeignKey('self', null=True)

    cdate = models.DateField(blank=True, null=True, default=datetime.date.today())
    udate = models.DateField(blank=True, null=True, default=datetime.date.today())
    ddate = models.DateField(blank=True, null=True)

    def __unicode__(self):
        return '(' + self.group.code + ', ' + self.code + ') ' + self.name

    class Meta:
        unique_together = ("group", "code",)





class CompanyCodes(models.Model):
    '''회사에 통용되는 마스터 코드
    '''
    company = models.ForeignKey(Companies)
    
    code = models.CharField(max_length=20)
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=2000)

    memo = models.TextField(null=True, blank=True)
    used = models.BooleanField(default=True)
    sort_seq = models.IntegerField(default=1)

    upper_code = models.ForeignKey('self', null=True)


    cdate = models.DateField(blank=True, null=True, default=datetime.date.today())
    udate = models.DateField(blank=True, null=True, default=datetime.date.today())
    ddate = models.DateField(blank=True, null=True)

    def __unicode__(self):
        return '(' + self.company.group.code + ', '+ self.company.code + ', '+ self.code + ') ' + self.name

    class Meta:
        unique_together = ("company", "code",)




"""
class MasterCode(models.Model):
    '''마스터 코드
    '''
    house_code = models.CharField(max_length=10)
    code = models.CharField(max_length=20)

    description = models.CharField(max_length=200)
    memo = models.TextField(null=True, blank=True)
    used = models.BooleanField(default=True)
    sort_seq = models.IntegerField(default=1)
    #super_code = models.CharField(max_length=20, null=True, blank=True)

    super_code = models.ForeignKey('self', null=True)


    cdate = models.DateField(blank=True, null=True, default=datetime.date.today())
    udate = models.DateField(blank=True, null=True, default=datetime.date.today())
    ddate = models.DateField(blank=True, null=True)

    def __unicode__(self):
        return '(' + self.code + ') ' + self.description

    class Meta:
        #models.unique_together = (("house_code", "code"),)
        unique_together = ("house_code", "code",)
"""


class UserProfiles(models.Model):
    '''사용자 모델 확장'''
    user = models.OneToOneField(User)
    dept = models.OneToOneField(Depts)
    
    tel_no = models.CharField(max_length=30)
    #picture = models.ImageField(blank=True, null=True, upload_to="upload/picture/")

    # /home/ok49/development/project/django/WorkManager/resources
    picture = models.ImageField(blank=True, null=True, upload_to='WorkManager/resources/')


    cdate = models.DateField(blank=True, null=True, default=datetime.date.today())
    udate = models.DateField(blank=True, null=True, default=datetime.date.today())
    ddate = models.DateField(blank=True, null=True)
    
    def __unicode__(self):
        return '(' + self.user.username  + ') ' + self.user.email
    
    
    def get_profile(self):
        return ""









    
    



class DeptDao:


    def add_dept(self):
        
        company = Companies.objects.get(code='CC01')

        d = Depts.objects.get(code='D002')
        
        nd = Dept(company=company,
                  code='D004',
                  expire_date='9999-12-31',
                  dept_name='개발2팀',
                  sort_no=2
                  )
        
        nd.save()

        udt = DeptTrees.objects.filter(descendant=d)
        
        for i in udt:
            DeptTrees.objects.create(ancestor=i.ancestor, descendant=nd, path_length=i.path_length + 1)
        DeptTrees.objects.create(ancestor=nd, descendant=nd, path_length=0)
        



    '''
    부서 DAO
    '''
    """
    def get_dept_upper_object(self, dept):
        '''
        상위부서 객체를 반환
        '''
        try:
            dept_object = Depts.objects.get(code=dept.super_dept_code)

            return dept_object
        except Dept.DoesNotExist:
            return None
    """

    def get_dept_json(self, group_code, company_code, upper_dept_id=None):

        company = Companies.objects.get(group=Groups.objects.get(code=group_code), code=company_code)

        log.info("@@@@@@@@@@@@@@@@ 회사 = " + str(company))

        dt = []
        if upper_dept_id is None or upper_dept_id == '':
            # 상위코드가 없을때
            d = Depts.objects.filter(
                company = company,
                code='root',
                expire_date__gte = '2011-11-15')


            #log.info("부서 = " + str(d))


            dt = DeptTrees.objects.filter(ancestor=d, descendant=d)

            log.info("부서트리 = " +  str(dt))


        else:
            #요청된 상위코드가 있다면

            log.info("$$$$$$$$$$$$$$$$$$$$$$$$$$$")

            d = Depts.objects.get(
                        company=company,
                        expire_date__gte = '2011-11-15',
                        code=upper_dept_id
                        )

            #log.info('d = ' + str(d))

            dt = DeptTrees.objects.filter(ancestor=d, path_length=1)

            log.info("dt = " + str(dt))





        o = []
        for i in dt:

            rel = ''
            child_node = ''
            valid_children = ''

            log.info("야하")
            log.info(len(dt))

            #log.info(DeptTree.objects.filter(ancestor=d).exclude(ancestor=d, descendant=d))

            if len(DeptTrees.objects.filter(ancestor=i.descendant, path_length=1)) > 0:
                log.info("***************************************")

                '''하위 노드가 있는지 판단한다'''

                child_node = 'closed'
                valid_children=  "[ \"default\", \"folder\" ]"
                rel = 'folder'
            else:
                log.info("자식 노드 없음류")
                child_node = ''
                valid_children = "\"none\""
                rel ='default'

            log.info("CHILD_NODE = " + child_node)

            if upper_dept_id is None or upper_dept_id == '':
                rel='driver'

            k = {"data":i.descendant.name, "state":child_node,
                 "attr": {"id":i.descendant.code, "rel":rel},
                        "metadata": {"id":i.descendant.code, "description":i.descendant.name}
                            }

            o.append(k)
        logging.debug(o)

        return o

    def get_child_node(self, dept_name):
        o = []


        flag = True

        first = True
        d = Dept.objects.filter(dept_name__startswith=dept_name)

        logging.debug('-----------------------------')
        logging.debug(d)
        logging.debug('-----------------------------')


        dept_code = None
        super_dept_code = None

        if len(d) > 0 :
            while(flag):

                if first:

                    if len(d) > 0:
                        dept_code = d[0].dept_code
                        super_dept_code = d[0].super_dept_code

                        o.append('#' + dept_code)

                    first = False

                else:

                    #d = Dept.objects.filter(dept_code=super_dept_code)
                    logging.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
                    logging.info(super_dept_code)
                    logging.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")

                    d = super_dept_code

                    dept_code = d.dept_code
                    super_dept_code = d.super_dept_code

                    o.insert(0, '#' + dept_code)


                if super_dept_code == None:
                    flag = False


        logging.info(o)

        return o

'''
class DeptDaoTestCase(unittest.TestCase):
    def setup(self):
        None

    def test_get_dept_upper_object(self):
        create_fakedata()

        dao = DeptDao()
        d = Dept.objects.get(dept_code='B1000000000000000000')
        dept = dao.get_dept_upper_object(Dept.objects.get(
            dept_code='B1000000000000000000'))

        self.assertEqual(dept.dept_code, 'A1000000000000000000')


        dept = dao.get_dept_upper_object(Dept.objects.get(
            dept_code='C1000000000000000001'))

        self.assertEqual(dept.dept_code, 'B1000000000000000000')


        dept = dao.get_dept_upper_object(Dept.objects.get(
            dept_code='A1000000000000000000'))

        self.assertEqual(dept,  None)

'''